home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2008 September
/
PCWorld_2008-09_cd.bin
/
v cisle
/
sadanastroju
/
bookmark_previews-0.6.5-fx.xpi
/
chrome
/
content
/
albumview.js
next >
Wrap
Text File
|
2008-05-27
|
17KB
|
472 lines
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Bookmark Previews extension.
*
* The Initial Developer of the Original Code is
* John Marshall <JohnM555@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Marshall <JohnM555@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var AlbumView = {
initiated : false,
container : null,
img_container : null,
caption : null,
keepFocus : true,
updatedSelection : false,
current: 0, target: 0, timer: 0,
middle : 0, vscale : 0, hscale : 0, max : 0,
MAX_NODES: 9,
lastOffsets : [],
itemNodes : [],
itemImages : [],
itemProps : [],
canRefresh : true,
STEP_INTERVAL : 50,
SHOW_REFLECTION : false,
init : function(aContainer, aImgContainer, aCaption){
this.canvas = document.getElementById("albumcanvas");
this.container = document.getElementById("albumview-container");
this.img_container = document.getElementById("albumview-image-container");
this.caption = document.getElementById("albumview-caption");
this.scrollbar = document.getElementById("albumview-scrollbar");
this.container.addEventListener('click',this.displayClick,false);
this.container.addEventListener('dblclick',this.displayDblClick,false);
this.container.addEventListener('DOMMouseScroll', this.wheel, false);
this.scrollbar.addEventListener('DOMAttrModified',this.onScroll,false);
this.container.addEventListener('DOMAttrModified',this.onCollapse,false);
this.container.addEventListener('keypress',this.handleKeypress,true);
//this.container.addEventListener('click',this.containerClick,false);
},
uninit : function(){
this.scrollbar.removeEventListener('DOMAttrModified',this.onScroll,false);
this.container.removeEventListener('click',this.displayClick,false);
this.container.removeEventListener('dblclick',this.displayDblClick,false);
this.container.removeEventListener('DOMMouseScroll', this.wheel, false);
this.container.removeEventListener('DOMAttrModified',this.onCollapse,false);
this.container.removeEventListener('keypress',this.handleKeypress,true);
//this.container.removeEventListener('click',this.containerClick,false);
this.initiated = false;
},
/* called on start and on refresh
caches unchanging values
orient = -1, its initializing the album view
orient = 0, resized horizontally
orient = 1, resized vertically
*/
refresh : function(orient) {
this.canRefresh = false;
this.width = this.container.boxObject.width;
this.middle = this.width / 2;
if (!this.previousHeight)
this.height = Math.ceil(.25 * this.width);
else{
this.height = this.previousHeight;
this.previousHeight = null;
}
var otherHeight = this.caption.parentNode.boxObject.height;
var curHeight = this.container.boxObject.height - otherHeight;
var availableHeight = this.container.parentNode.boxObject.height - otherHeight;
if (this.initiated && orient!=0){
availableHeight = this.container.boxObject.height - otherHeight;
} else if (!this.initiated)
this.initiated = true;
if (availableHeight<this.height){
this.height = availableHeight;
}
this.slope = (this.height)/(this.width/2);
this.vscale = this.height * 1.193181818;
this.hscale = 5 * this.height / 2;
this.scrollbar.width = this.width-10;
this.setSize(this.img_container, this.width, this.height);
this.setSize(this.img_container.parentNode, this.width, this.height);
this.img_container.parentNode.parentNode.width = this.width;//.style.maxWidth = width;
this.container.height = this.height+otherHeight;
/* Display images in current order */
this.moveTo(this.current);
this.canRefresh = true;
},
onCollapse : function(event){
if (event.attrName == "collapsed"){
var collapsed = event.newValue;
if (collapsed && AlbumView.height >=20){
AlbumView.previousHeight = AlbumView.height;
} else
AlbumView.previousHeight = 0;
}
},
step : function() {
var self = AlbumView;
if (self.target < self.current-1 || self.target > self.current+1) {
self.moveTo(self.current + (self.target-self.current)/3);
setTimeout(self.step, self.STEP_INTERVAL);
self.timer = 1;
} else {
self.timer = 0;
self.current = self.target;
var targetIndex = -AlbumView.target/150
if (AlbumViewUtils && AlbumViewUtils.selectIndex)
AlbumViewUtils.selectIndex(self.itemNodes[targetIndex]);
}
},
glideToIndex : function(index){
var target = index * -150;
AlbumView.glideTo(target);
},
glideTo : function(aTarget,updateSelection) {
/* Animate gliding to new x position */
this.target = aTarget;
var targetIndex = -this.target/150;
var currentIndex = -this.current/150;
if (targetIndex>=this.max){
if (currentIndex<this.max-1){
this.target = -(this.max-1)*150;
targetIndex = -this.target/150;
}
}
if (this.timer == 0 && targetIndex<this.max && targetIndex!=currentIndex){
setTimeout(this.step, 50);
this.timer = 1;
}
this.updateCaption(Math.ceil(targetIndex));
},
updateCaption : function(index){
if (index<this.max && index>-1 && this.itemProps.length>0){
/* Display new caption */
var caption = this.itemProps[index].caption;
this.caption.value = caption;
/* Update scrollbar */
this.scrollbar.setAttribute("curpos",index);
} else{
this.caption.value = "";
this.scrollbar.setAttribute("curpos",0);
}
},
onScroll : function(event){
if (event.attrName == "curpos"){
AlbumView.glideToIndex(event.newValue);
}
},
/* main part of the transition */
moveTo : function(x) {
//dump("moveto: "+x+"\n");
try{
var self = AlbumView;
self.current = x;
var targetIndex = Math.ceil(-self.target / 150);
var currentIndex = Math.ceil(-self.current / 150);
var start=targetIndex-self.MAX_NODES;
if (start<0)
start=0;
var end=targetIndex+self.MAX_NODES;
if (end>self.max - 1)
end = self.max - 1;
var ctx = self.img_container.getContext("2d");
ctx.clearRect(0,0,self.width,self.height);
function moveLoop(index,increasing){
self.computeProperties(x,self.itemProps[index]);
var success = self.drawImage(index, targetIndex);
x = increasing?x+150:x-150;
}
x = x + 150 * start;
for (var index = start; index < targetIndex; index++){
moveLoop(index,true);
}
x = self.current + end * 150;
for (var index = end; index>=targetIndex; index--){
moveLoop(index, false);
}
}catch(e){Components.utils.reportError("MOVETO: "+e);}
},
computeProperties : function(x, props){
var z = Math.sqrt(10000 + Math.pow(x,2))+100;
if (!props) return;
props.width = Math.floor(200 / z * this.vscale);
props.height = Math.floor(220 / z * this.vscale -
25 / z * this.hscale);
props.left = Math.floor((x / (Math.sqrt(10000 + Math.pow(x,2))+300))*this.hscale + this.middle - props.width/2);
props.top = Math.floor((this.height - props.height)/2);
//dump("props["+x+"] = width: "+props.width+" height: "+props.height+" left: "+props.left+" top: "+props.top+"\n");
},
/* returns true if it should be drawn, false if it shouldn't(out of bounds)*/
drawImage : function(index, targetIndex){
try{
var self = AlbumView;
if (!targetIndex)
targetIndex = -self.target / 150;
var offset = index - targetIndex;
var props = self.itemProps[index];
if (!props || props.left == null)
return false;
if (props.left<0 || props.width <= 0 || props.left+props.width>self.width){
return false;
}
var ctx = self.img_container.getContext("2d");
var img = self.itemImages[index];
if (img.complete){
var hoffset = 0, toffset = 0;
/* not finished... */
if (false && ctx.transform && offset!=0){/* FF3 only*/
if (!self._tempCanvas){
self._tempCanvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas");
}
var angle = 0, tanA = 0;
if (offset < 0){
angle = -Math.PI / 18;
tanA = Math.tan(angle);
hoffset = Math.abs(props.height * tanA * 2);
toffset = hoffset;
}
else{
angle = Math.PI / 18;
tanA = Math.tan(angle);
hoffset = props.height * tanA * 2;
}
self.setSize(self._tempCanvas,props.width,props.height+hoffset);
var ctx2 = self._tempCanvas.getContext("2d");
ctx2.clearRect(0,0,img.width,props.height+hoffset);
ctx2.transform(1, tanA, 0, 1, 0, 0);
ctx2.drawImage(img,0,toffset,props.width,props.height);
img = self._tempCanvas;
}
var adjustedHeight=props.width/img.width*img.height;
if (props.width>img.width) adjustedHeight = props.height;
var adjustedTop = (props.height-adjustedHeight)/1+props.top;
adjustedTop = props.top; adjustedHeight = props.height;
ctx.drawImage(img,
props.left,
adjustedTop,
props.width,
adjustedHeight);
if (self.SHOW_REFLECTION && ctx.transform){
var rheight = Math.ceil(props.height/3);
if (rheight+props.top+props.height>self.height){
rheight = self.height-props.height-props.top;
}
if (rheight>1){
if (!self._tempCanvas){
self._tempCanvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas");
}
self.setSize(self._tempCanvas,props.width,props.height+hoffset);
var ctx2 = self._tempCanvas.getContext("2d");
ctx2.clearRect(0,0,img.width,props.height+hoffset);
ctx2.transform(1, 0, 0, -1, 0, props.height);
ctx2.drawImage(img,0,0,props.width,props.height);
img = self._tempCanvas;
ctx.drawImage(img, 0, 0, img.width, img.height,
props.left,
props.top+props.height,
props.width,
rheight);
var lineargradient = ctx.createLinearGradient(0,props.top+props.height,0,props.top+props.height+rheight);
lineargradient.addColorStop(0,'rgba(0,0,0,.3)');
lineargradient.addColorStop(.5,'rgba(30,30,30,.7)');
lineargradient.addColorStop(1,'rgba(0,0,0,1)');
ctx.fillStyle = lineargradient;
ctx.fillRect(props.left,props.top+props.height,props.width,rheight);
}
}
}
//else{
// //dump("draw image was called but the image was not complete: "+index+"\n");
//}
self.lastOffsets[index] = offset;
//dump("finish draw image\n");
}catch(e){Components.utils.reportError(e);}
return true;
},
_getClickTarget : function(event){
var x = (event.clientX - this.container.boxObject.x);//event.layerX;
var y = (event.clientY - this.container.boxObject.y);//event.layerY;
var targetIndex = -this.target / 150;
/* less than or equal to targetIndex */
if (x<this.middle){
for (var i = Math.ceil(targetIndex); i>=0; i--){
var props = this.itemProps[i];
if (props && x>=props.left && x<=props.left + props.width){
return i;
}
}
}
else{
for (var i = Math.floor(targetIndex); i< this.max; i++){
var props = this.itemProps[i];
if (x>=props.left && x<=props.left + props.width){
return i;
}
}
}
return -1;
},
displayClick : function(event){
var index = AlbumView._getClickTarget(event);
if (index == -1) return;
if (event.button == 1)
AlbumViewUtils.performAction(AlbumView.itemNodes[index],event);
else
AlbumView.glideTo(index * -150,true);
},
displayDblClick : function(event){
var index = AlbumView._getClickTarget(event);
if (index != -1){
AlbumViewUtils.performAction(AlbumView.itemNodes[index],event);
}
},
/* JavaScript mouse wheel */
handle : function(delta) {
if (delta > 0) {
if(AlbumView.target != 0)
AlbumView.target += 150;
} else if(-AlbumView.target/150 < AlbumView.max) {
AlbumView.target = AlbumView.target - 150;
}
AlbumView.glideTo(AlbumView.target,true);
},
/* JavaScript mouse wheel support */
wheel : function(event){
var delta = -event.detail/3;
AlbumView.handle(delta);
//event.preventDefault();
},
handleKeypress : function(event){
var KeyEvent = Ci.nsIDOMKeyEvent;
switch(event.keyCode){
case KeyEvent.DOM_VK_LEFT:
AlbumView.handle(1)
break;
case KeyEvent.DOM_VK_RIGHT:
AlbumView.handle(-1);
break;
//TODO: This won't work since it isn't focusable anymore
case KeyEvent.DOM_VK_RETURN:
case KeyEvent.DOM_VK_ENTER:
if (AlbumViewUtils && AlbumViewUtils.performAction){
var targetIndex = -AlbumView.target/150;
AlbumViewUtils.performAction(AlbumView.itemNodes[targetIndex]);
}
}
},
createImages : function(aImages){
var totalImages = aImages;
AlbumView.caption.value = "";
AlbumView.max = totalImages.length;
AlbumView.itemNodes = new Array(AlbumView.max);
AlbumView.itemImages = new Array(AlbumView.max);
AlbumView.itemProps = new Array(AlbumView.max);
/* remove any remaining children */
for (var i = AlbumView.max-1; i>=0; i--){
var src = totalImages[i];
AlbumView.lastOffsets[i]=i;
AlbumView.itemNodes[i]=src.node;
AlbumView.itemProps[i] = {caption : src.caption,
url : src.url};
AlbumView.itemImages[i]=new Image();
AlbumView.itemImages[i].setAttribute("onload",
"AlbumView.imageLoaded("+i+");");
AlbumView.itemImages[i].src = src.image;
if (AlbumView.itemImages[i].complete){
AlbumView.imageLoaded(i);
}
}
this.scrollbar.setAttribute("maxpos",AlbumView.max-1);
},
clearItems : function(){
this.max = 0;
this.itemNodes = [];
this.itemProps = [];
this.itemImages = [];
this.scrollbar.setAttribute("maxpos",0);
},
addItem : function(aItem){
var i = this.itemNodes.length;
this.scrollbar.setAttribute("maxpos",i);
this.max = i+1;
this.itemNodes.push(aItem.node);
this.itemProps.push({caption: aItem.caption,
url: aItem.url});
if (i == 0){
this.caption.value = aItem.caption;
}
var img = new Image();
this.itemImages.push(img);
let j = i;
img.onload = function(){
AlbumView.imageLoaded(j);
}
img.src = aItem.image;
if (img.complete)
this.imageLoaded(i);
},
imageLoaded : function(idx){
if (!AlbumView.initiated)
return;
/*
Simply drawing the image once it has loaded won't work because then we could have
thumbnails on top of those closer to the center. We need to loop from the
last added thumbnail to center to avoid this problem.
If the image is out of view we don't need to draw anything else
*/
var x = AlbumView.current + 150 * idx;
AlbumView.computeProperties(x,AlbumView.itemProps[idx]);
var targetIndex = -AlbumView.target / 150, canDraw = true;
if (idx>=targetIndex){
for (var i = idx; canDraw && i>=targetIndex; i--){
canDraw = AlbumView.drawImage(i, targetIndex);
}
}
else if (idx<targetIndex){
for (var i = idx; canDraw && i<=targetIndex; i++){
canDraw = AlbumView.drawImage(i, targetIndex);
}
}
},
setSize : function(ele,width,height){
ele.setAttribute("height",height);
ele.setAttribute("width",width);
ele.width=width;
ele.height=height;
ele.style.maxWidth = width;
}
}